var obj = {
  name: '王国峰',
  age: 25,
  info: {
    hobby: ['travel', 'piano'],
    career: {
      teacher: 4,
      engineer: 9
    }
  }
}

// // ES5
// function deepClone(origin, target) {
//   var tar = target || {};
//   var toStr = Object.prototype.toString()
//   var arrayType = '[object Array]'

//   for (var key in origin) {
//     if (origin.hasOwnProperty(key)) {
//       if (typeof origin[key] === 'object' && origin[key] !== null) {
//         tar[key] = toStr.call(origin[key]) === arrayType ? [] : {}
//         deepClone(origin[key], tar[key])
//       } else {
//         tar[key] = origin[key]
//       }
//     }
//   }

//   return tar;
// }

/**
 * WeakMap
 *
 * 经常与 Map 相比
 *
 * 首先都是 键值对
 * 
 * Map 键名 可以是任意类型
 * WeakMap 键名 只能是对象
 */

// const oBtn1 = document.querySelector('#btn1')
// const oBtn2 = document.querySelector('#btn2')

// oBtn1.addEventListener('click', handleoBtn1, false)
// oBtn2.addEventListener('click', handleoBtn2, false)

// // 如果按钮移除，事件内存无法回收
// oBtn1.remove()
// oBtn2.remove()

// function handleoBtn1 () {}
// function handleoBtn2 () {}

// // 需要手动处理
// handleoBtn1 = null
// handleoBtn2 = null

// // WeakMap 可以用来处理该类问题
// const oBtnMap = new WeakMap()
// oBtnMap.set(oBtn1, handleoBtn1)
// oBtnMap.set(oBtn2, handleoBtn2)

// // 事件便可以如此绑定
// // weakMap 键名是弱引用 -》 即键名不存在，则值会被处理
// oBtn1.addEventListener('click', oBtnMap.get(oBtn1), false)
// oBtn2.addEventListener('click', oBtnMap.get(oBtn2), false)



function deepClone (origin, hashMap = new WeakMap()) {
  // null undefined
  if(origin == undefined || typeof origin !== 'object') { // null undefined
    return origin
  }

  // Date RegExp
  if(origin instanceof Date) {
    return new Date(origin)
  }

  if(origin instanceof RegExp) {
    return new RegExp(origin)
  }

  const hashKey = hashMap.get(origin)

  if(hashKey) {
    return hashKey
  }

  // {} [] 利用构造器
  const target = new origin.constructor()
  hashMap.set(origin, target)
  console.log('target', target)
  for(let key in origin) {
    console.log(key)
    if(origin.hasOwnProperty(key)) {
      target[key] = deepClone(origin[key], hashMap)
    }
  }

  return target;
}

// 是否拷贝过
let test1 = {}
let test2 = {}

test2.test1 = test1;
test1.test2 = test2;

console.log(test2, deepClone(test2))
